package com.jiazhong.mingxing.boot.boot05.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jiazhong.mingxing.boot.boot05.bean.Student;
import com.jiazhong.mingxing.boot.boot05.mapper.StudentMapper;
import com.jiazhong.mingxing.boot.boot05.service.StudentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
public class StudentServiceImpl extends ServiceImpl<StudentMapper, Student> implements StudentService {

    private StringRedisTemplate stringRedisTemplate;
    private StudentMapper studentMapper;
    private ValueOperations<String, String> forValue;
    private ListOperations<String, String> forList;

    public static final String PREFIX_STUDENT = "PREFIX_STUDENT_";

    public static final String ALL_STUDENT = "ALL_STUDENT";

    @Autowired
    public StudentServiceImpl(StringRedisTemplate stringRedisTemplate, StudentMapper studentMapper) {
        this.stringRedisTemplate = stringRedisTemplate;
        this.studentMapper = studentMapper;
        this.forValue = stringRedisTemplate.opsForValue();
        this.forList = stringRedisTemplate.opsForList();
    }

    @Override
    public Student findStudentById(String id) {
        log.info("开始查询id:{}的数据", id);
        // 1. 从redis中获取到制定ID的数据
        String studentJSON = forValue.get(PREFIX_STUDENT + id);
        log.info("返回id:{}的数据:{}", id, studentJSON);
        // 2. 如果存在，返回该数据
        if (studentJSON != null) {
            log.info("存在该数据，结束！");
            return JSONArray.parseObject(studentJSON, Student.class);
        }
        // 3. 如果不存在该数据，从数据库中获取
        Student student = studentMapper.selectById(id);
        log.info("不存在该数据，从数据库中获取该数据:{}", student);
        // 4. 存放到redis中
        String jsonString = JSONArray.toJSONString(student);
        forValue.set(PREFIX_STUDENT + id, jsonString, 1, TimeUnit.HOURS);
        log.info("存放数据到redis中");
        // 5. 返回数据
        return student;
    }

    @Override
    public List<Student> findAll1() {
        // 1. 从redis中获取
        String json = forValue.get(ALL_STUDENT);
        // 2. 如果存在，返回数据，结束
        if (json != null) {
            return JSONArray.parseArray(json, Student.class);
        }
        // 3. 如果不存在，链接数据库
        List<Student> all_students = this.list();
        // 4. 将数据存放到redis中
        String jsonString = JSONArray.toJSONString(all_students);
        forValue.set(ALL_STUDENT, jsonString, 1, TimeUnit.HOURS);
        // 5. 返回数据
        return all_students;
    }

    @Override
    public List<Student> findAll2() {
        // 1. 从redis中获取
        List<String> stringList = forList.range(ALL_STUDENT, 0, -1);
        // 2. 如果存在，返回数据，结束
        if (stringList != null && !stringList.isEmpty()) {
            List<Student> all_students = new ArrayList<>();
            stringList.forEach(s -> {
                Student student = JSONArray.parseObject(s, Student.class);
                all_students.add(student);
            });
            return all_students;
        }
        // 3. 如果不存在，链接数据库
        List<Student> list = this.list();
        // 4. 将数据存放到redis中
        list.forEach(student -> {
            String s = JSONArray.toJSONString(student);
            forList.rightPush(ALL_STUDENT, s);
        });
        // 5. 返回数据
        return list;
    }

    @Override
    public List<Student> findAll3() {
        // 1. 从redis中获取
        List<String> stringList = forList.range(ALL_STUDENT, 0, -1);
        // 2. 如果存在，返回数据，结束
        if (stringList != null && !stringList.isEmpty()) {
            List<Student> all_students = new ArrayList<>();
            stringList.forEach(id -> {
                String json = forValue.get(id);
                Student student = JSONArray.parseObject(json, Student.class);
                all_students.add(student);
            });
            return all_students;
        }
        // 3. 如果不存在，链接数据库
        List<Student> list = this.list();
        // 4. 将数据存放到redis中
        list.forEach(student -> {
            // 4.1 将id存放到集合中
            forList.rightPush(ALL_STUDENT, student.getId() + "");
            // 4.2 将对象存放到了string中
            forValue.set(student.getId() + "", JSONArray.toJSONString(student));
        });
        // 5. 返回数据
        return list;
    }

    /*public int saveStudent(Student student) {
        // 1. 将数据添加到数据库中
        boolean b = this.save(student);
        // 2. 将刚才录入到数据库的数据查询出来
        QueryWrapper<Student> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("name", student.getName());
        queryWrapper.eq("stu_no", student.getStuNo());
        Student one = getOne(queryWrapper);
        // 3. 将数据添加到缓存中
        String s = JSONArray.toJSONString(one);
        forList.rightPush(ALL_STUDENT, s);
        return b ? 1 : 0;
    }*/

    @Override
    public int saveStudent(Student student) {
        // 1. 将数据添加到数据库中
        boolean b = this.save(student);
        // 2. 将刚才录入到数据库的数据查询出来
        QueryWrapper<Student> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("name", student.getName());
        queryWrapper.eq("stu_no", student.getStuNo());
        Student one = getOne(queryWrapper);
        // 3. 将数据添加到缓存中
        // 3.1 将one存放到string中
        forValue.set(one.getId() + "", JSONArray.toJSONString(one));
        // 3.2 将id存放到索引区list
        forList.rightPush(ALL_STUDENT, one.getId() + "");
        return b ? 1 : 0;
    }

    /*public int updateStudent(Student student) {
        // 1. 修改数据库中的数据
        boolean b = updateById(student);
        // 2. 取出刚修改的数据
        QueryWrapper<Student> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("id", student.getId());
        Student sqlStudent = getOne(queryWrapper);
        // 3. 修改redis缓存中的数据
        List<String> stringList = forList.range(ALL_STUDENT, 0, -1);
        if (stringList != null && !stringList.isEmpty()) {
            final int[] index = {0};
            stringList.forEach(s -> {
                Student one = JSONArray.parseObject(s, Student.class);
                if (one.getId().equals(student.getId())) {
                    forList.set(ALL_STUDENT, index[0], JSONArray.toJSONString(sqlStudent));
                }
                index[0]++;
            });
        }
        return b ? 1 : 0;
    }*/

    @Override
    public int updateStudent(Student student) {
        // 1. 修改数据库中的数据
        boolean b = updateById(student);
        // 2. 取出刚修改的数据
        QueryWrapper<Student> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("id", student.getId());
        Student sqlStudent = getOne(queryWrapper);
        // 3. 修改redis中的数据
        forValue.setIfPresent(sqlStudent.getId() + "", JSONArray.toJSONString(sqlStudent));
        return 0;
    }

    @Override
    public int removeStudentById(String id) {
        // 1. 删除数据库中的数据
        boolean b = removeById(id);
        // 2. 将redis中的数据删除
        forList.remove(ALL_STUDENT, 1, id + "");
        stringRedisTemplate.delete(id + "");
        return b ? 1 : 0;
    }
}
